package com.richinfo.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.richinfo.exception.JsonDeserializationException;
import com.richinfo.exception.JsonSerializationException;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * JSON数据转换工具，基于Jackson.
 * 
 **/
public class JsonUtils {
	public static ObjectMapper defaultMapper = new ObjectMapper();
	public static ObjectMapper pascalMapper = new ObjectMapper();

	private static ObjectMapper[] mappers = { defaultMapper, pascalMapper };

	/*
	 * 配置
	 */
	static {
//		JsonSerializer nullValueSerializer = new JsonSerializer<Object>(){
//
//			@Override
//			public void serialize(Object arg0, JsonGenerator arg1, SerializerProvider arg2)
//					throws IOException, JsonProcessingException {
//				arg1.writeString("");
//			}
//			
//		};
		
		for (ObjectMapper mapper : mappers) {
			// 反序列化配置
			mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); // 支持控制字符，如tab、换行符
			mapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);// 支持转义
			mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);// 允许属性名不使用引号
			mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);// 允许属性名用单引号
			mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略json串中有，但是类中没有的字段
			mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);

			// 序列化配置
			mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// null的属性不序列化
			mapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS, true);// 序列化char[]时以json数组输出，默认false
			mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);// 支持空对象
			mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
			
			//mapper.getSerializerProvider().setNullValueSerializer(nullValueSerializer);
		}

		pascalMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy());

	}

	/**
	 * 序列化.
	 */
	public static String write(Object obj) {
		String json = null;

		if (obj == null) {
			return "";
		}

		try {
			json = defaultMapper.writeValueAsString(obj);
		} catch (Exception e) {
			throw new JsonSerializationException(e);
		}

		return json;
	}

	/**
	 * 序列化（Pascal命名策略，首字母大写）.
	 */
	public static String writePascal(Object obj) {
		String json = null;

		if (obj == null) {
			return "";
		}

		try {
			json = pascalMapper.writeValueAsString(obj);
		} catch (Exception e) {
			throw new JsonSerializationException(e);
		}

		return json;
	}

	/**
	 * 反序列化（Pascal命名策略，首字母大写）.
	 */
	public static <T> T readPascal(String json, TypeReference<T> valueTypeRef) {
		T t = null;

		if (StringUtils.isEmpty(json)) {
			return null;
		}

		try {
			t = pascalMapper.readValue(json, valueTypeRef);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}

		return t;
	}

	/**
	 * 反序列化（Pascal命名策略，首字母大写）.
	 */
	public static <T> T readPascal(String json, Class<T> entityClass) {
		T t = null;

		if (StringUtils.isEmpty(json)) {
			return null;
		}

		try {
			t = pascalMapper.readValue(json, entityClass);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}

		return t;
	}

	/**
	 * 反序列化（支持带泛型的容器）.<br>
	 */
	public static <T> T readPascalAsContainer(String json, Class<?> containerClass, Class<?>... entityClasses) {
		JavaType valueType = pascalMapper.getTypeFactory().constructParametricType(containerClass, entityClasses);

		T t = null;
		try {
			t = pascalMapper.readValue(json, valueType);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}
		return t;
	}

	/**
	 * 反序列化.
	 */
	public static <T> List<T> readPascalAsList(String json, Class<T> entityClass) {
		return readAsContainer(json, List.class, entityClass);
	}

	/**
	 * 反序列化.
	 */
	public static Map<String, String> readPascalAsMap(String json) {
		return readAsContainer(json, Map.class, String.class, String.class);
	}

	public static <T> T read(String json, TypeReference<T> valueTypeRef) {
		T t = null;

		if (StringUtils.isEmpty(json)) {
			return null;
		}

		try {
			t = defaultMapper.readValue(json, valueTypeRef);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}

		return t;
	}

	/**
	 * 反序列化（简单实体类）.
	 */
	public static <T> T read(String json, Class<T> entityClass) {
		T t = null;

		if (StringUtils.isEmpty(json)) {
			return null;
		}

		try {
			t = defaultMapper.readValue(json, entityClass);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}

		return t;
	}

	/**
	 * 反序列化（支持带泛型的容器）.<br>
	 */
	public static <T> T readAsContainer(String json, Class<?> containerClass, Class<?>... entityClasses) {
		JavaType valueType = defaultMapper.getTypeFactory().constructParametricType(containerClass, entityClasses);

		T t = null;
		try {
			t = defaultMapper.readValue(json, valueType);
		} catch (Exception e) {
			throw new JsonDeserializationException(json, e);
		}
		return t;
	}

	/**
	 * 反序列化.
	 */
	public static <T> List<T> readAsList(String json, Class<T> entityClass) {
		return readAsContainer(json, List.class, entityClass);
	}

	/**
	 * 反序列化.
	 */
	public static Map<String, Object> readAsMap(String json) {
		return readAsContainer(json, Map.class, String.class, Object.class);
	}
}
